home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
lcsrc.arc
/
KEY_INT.ASM
< prev
next >
Wrap
Assembly Source File
|
1985-04-18
|
7KB
|
347 lines
page 60,132
title IBM PC Communications I/O Routines -- Curt Klinsing
interrupts segment at 0h
org 9h*4
keyboard_int label word
interrupts ends
include dos.mac
IF LPROG
X EQU 6 ;OFFSET OF ARGUMENTS
ELSE
X EQU 4 ;OFFSET OF ARGUMENTS
ENDIF
PSEG
;
;
;A set of Lattice C callable functions to support
;interrupt driven character I/O on the IBM PC. Input
;is buffered, output is polled.
;
public key_intercept ;initialize the comm port,
public key_nointercept ;remove initialization,
public key_intbcnt ;returns count of rcv chars,
public key_intbread ;get one char from buffer,
public key_intbflush ;flush input buffer,
;
FALSE EQU 0
TRUE EQU NOT FALSE
;
;
; MISCELLANEOUS EQUATES
;
BUFSIZ EQU 512 ;Max NUMBER OF CHARS
SetIntVect EQU 25H ;SET INTERRUPT VECTOR FUNCTION NUMBER
;
; DUMP BUFFER, COUNT AND POINTER.
;
CIRC_BUF DB BUFSIZ DUP(?) ;ALLOW 512 MaxIMUM BUFFERED CHARACTERS
BUF_TOP EQU $ - 1 ;KEEP TRACK OF THE TOP OF THE BUFFER
CIRC_TOP DW BUF_TOP ;
;
CIRC_IN DW OFFSET CIRC_BUF ;POINTER TO LAST CHAR. PLACED IN BUFFER
CIRC_CUR DW OFFSET CIRC_BUF ;POINTER TO NEXT CHAR. TO BE RETRIEVED FROM
; BUFFER
CIRC_CT DW 0 ;COUNT OF CHARACTERS USED IN BUFFER
junk dw 0,0,0
old_keyboard_int dw 0,0,0,0 ; storage for old keyboard vector
junk2 dw 0,0,0
;--------------------------------------------------------------
;
; name key_intercept - intercept hardware key interrupt
;
; synopsis key_intercept();
;
; description Intercepts the hardware keyboard interrupt. You can
; use this routine to gain absolute control over the
; keyboard. The disadvantage is that you have to work
; with scan codes directly, not nice ascii characters.
; Up to 512 scan codes are buffered.
;
; notes
; The key_nointercept routine MUST be called before
; leaving your program, or the machine will hang.
;
; You must not attempt to use any other routine that
; reads the keyboard, or your program will hang. This
; routine absolutely intercepts the keyboard.
;
; You are in control of the keyboard, but that means that
; it is your responsibility to manage the state of the
; shift keys, the caps lock, and numlock keys and any other
; command keys, like the control key.
;
; Each key returns two scan codes, one when pressed, one
; when released. The code returned when the key is pressed
; is called a MAKE code, the one returned when a key is
; released is called a BREAK code. The BREAK code is
; the same as the make code, except that the high order bit
; is set in the BREAK code.
;
;---------------------------------------------------------------------
IF LPROG
key_intercept PROC FAR
ELSE
key_intercept PROC NEAR
ENDIF
push bp
cli
push ds
assume ds:interrupts
mov ax,interrupts
mov ds,ax
mov ax,keyboard_int
mov old_keyboard_int,ax
mov ax,keyboard_int[2]
mov old_keyboard_int[2],ax
mov ax,offset IntHdlr
mov keyboard_int,ax
mov keyboard_int[2],cs
sti
pop ds
pop bp
ret
key_intercept endp
;------------------------------------------------------------------------
; name key_nointercept - remove keyboard interception
;
; synopsis VOID key_nointercept()
;
; description Removes the interrupt structure installed by key_intercept.
; Must be done before passing control to DOS, else your
; machine will hang.
;-----------------------------------------------------------------------
IF LPROG
key_nointercept PROC FAR
ELSE
key_nointercept PROC NEAR
ENDIF
push ds
assume ds:interrupts
cli
mov ax,interrupts
mov ds,ax
mov ax,old_keyboard_int
mov keyboard_int,ax
mov ax,old_keyboard_int[2]
mov keyboard_int[2],ax
pop ds
sti
ret
key_nointercept endp
;----------------------------------------------------------
;
; name key_intbcnt - Return # chars in interrupt buffer
;
; synopsis count = key_intbcnt();
;
; description Returns the number of scan codes available in the
; keyboard intercept interrupt buffer.
;
; notes Call this to make sure that there are keystrokes
; available before attempting to read a code out of
; the buffer. If there are no codes available, DO NOT
; attempt to read the buffer.
;
;--------------------------------------------------------------------
;
IF LPROG
key_intbcnt PROC FAR
ELSE
key_intbcnt PROC NEAR
ENDIF
push bp
push ds ; save data segment
push cs
pop ds ; move code seg addr to data seg reg
mov ax,circ_ct
pop ds
pop bp
ret
key_intbcnt endp
;----------------------------------------------------------------
;
; name key_intbflush - Flush the interrupt buffer.
;
; synopsis VOID key_intbflush()
;
; description Flushes any key strokes in the keyboard interrupt
; intercept buffer.
;
;------------------------------------------------------------------
IF LPROG
key_intbflush PROC FAR
ELSE
key_intbflush PROC NEAR
ENDIF
push bp
push ds ; save data reg
push cs
pop ds ; move code seg addr to data seg reg.
mov bx,offset circ_buf
mov circ_in,bx
mov circ_cur,bx
xor ax,ax
mov circ_ct,ax
pop ds
pop bp
ret
key_intbflush endp
;------------------------------------------------------
;
; name key_intbread - get a char from the input buffer.
;
; synopsis ch = key_intbread();
;
; description returns the next character from the keyboard
; interrupt intercept buffer. Assumes you have called
; key_intbcnt to see if there are any characters to get.
;
; notes:
; Will probably crash if called when the buffer is
; empty. Call key_intbcnt first to see if there is
; anything available to read !!!!!!!!
;
;--------------------------------------------------------------------
IF LPROG
key_intbread PROC FAR
ELSE
key_intbread PROC NEAR
ENDIF
push bp
push ds ; save data reg
push cs
pop ds ; move code seg addr to data seg reg.
mov bx,circ_cur
xor ax,ax
mov al,[bx] ;get next char from circ_buf
DEC circ_ct ;decrement circ_buf COUNT
CMP bx,circ_top ;ARE WE AT THE TOP OF THE circ_buf?
JZ reset_cur ;JUMP IF SO
INC bx ;ELSE, BUMP PTR
JMP SHORT upd_cur
reset_cur:
mov bx,OFFSET circ_buf ;RESET circ_in TO BOTTOM OF BUF.
upd_cur:
mov circ_cur,bx ;SAVE NEW PTR
pop DS ;GET BACK ENTERING DS
pop bp
ret
key_intbread endp
;
kb_ctl equ 61h
;
IntHdlr proc far
CLI
push cx
push dx
push bx
push ax
push ds
mov ax,cs ;get cur code segment
mov ds,ax ; and set it as data segment
mov bx,circ_in ;GET circ_buf IN PTR
in al,60h
push ax ; save scan code
in al,kb_ctl
mov ah,al
or al,80h ; set "reset" bit
out kb_ctl,al
xchg ah,al
out kb_ctl,al
pop ax
mov ah,al
ck_full:
cmp circ_ct,BUFSIZ ;SEE IF circ_buf ALREADY FULL
jz clnup ; JUMP IF SO, DO NOT PLACE CHARACTER IN BFR
savch:
mov [bx],AL ;SAVE NEW CHARACTER IN circ_buf
inc circ_ct ;BUMP circ_buf COUNT
CMP bx,circ_top ;ARE WE AT THE TOP OF THE circ_buf?
JZ reset_in ;JUMP IF SO
inc bx ;ELSE, BUMP PTR
JMP SHORT into_buf
reset_in:
mov bx,OFFSET circ_buf ;RESET circ_in TO BOTTOM OF BUF.
into_buf:
mov circ_in,bx ;SAVE NEW PTR
clnup:
mov AL,20h
OUT 020h,AL ;ISSUE SPECIFIC EOI FOR 8259
pop ds ;GET BACK ENTERING DS
pop ax
pop bx
pop dx
pop cx
sti
iret
IntHdlr endp
endps
end